package projects

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	beego "github.com/beego/beego/v2/server/web"
	"strconv"
	"time"
	"xpms/app/models"
	"xpms/cores"
	"xpms/cores/utils"
)

type Projects struct {
	Id         int64 `orm:"pk;column(projectid);" json:"Id,string"`
	Userid     int64 `json:"Userid,string"`
	Name       string
	Aliasname  string
	Started    int64
	Ended      int64
	Desc       string
	Created    int64
	Status     int
	Projuserid int64 `json:"Projuserid,string"`
	Produserid int64 `json:"Produserid,string"`
	Testuserid int64 `json:"Testuserid,string"`
	Publuserid int64 `json:"Publuserid,string"`
}

type ProjectsAll struct {
	Id               int64 `json:"Id,string"`
	Userid           int64 `json:"Userid,string"`
	Userrealname     string
	Name             string
	Aliasname        string
	Started          int64
	Ended            int64
	Desc             string
	Created          int64
	Status           int
	Projuserid       int64 `json:"Projuserid,string"`
	Projuserrealname string
	Produserid       int64 `json:"Produserid,string"`
	Produserrealname string
	Testuserid       int64 `json:"Testuserid,string"`
	Testuserrealname string
	Publuserid       int64 `json:"Publuserid,string"`
	Publuserrealname string
}

func (this *Projects) TableName() string {
	return models.TableName("projects")
}
func init() {
	orm.RegisterModel(new(Projects))
}

func GetProject(id int64) (Projects, error) {
	var project Projects
	var err error

	err = utils.GetCache("GetProject.id."+fmt.Sprintf("%d", id), &project)
	if err != nil {
		o := orm.NewOrm()
		project = Projects{Id: id}
		err = o.Read(&project)
		utils.SetCache("GetProject.id."+fmt.Sprintf("%d", id), project, 600)
	}
	return project, err
}

func GetProjectByAliasname(name string) (Projects, error) {
	var project Projects
	var err error
	err = utils.GetCache("GetProject.Aliasname."+fmt.Sprintf("%d", name), &project)
	if err != nil {
		o := orm.NewOrm()
		o.QueryTable(models.TableName("projects")).Filter("aliasname", name).One(&project)
		utils.SetCache("GetProject.Aliasname."+fmt.Sprintf("%d", name), project, 600)
		if err == orm.ErrNoRows {
			return project, nil
		}
	}
	return project, err
}
func GetProjectName(id int64) string {
	var err error
	var name string

	err = utils.GetCache("GetProjectName.id."+fmt.Sprintf("%d", id), &name)
	if err != nil {
		cache_expire, _ := beego.AppConfig.Int("cache_expire")
		var project Projects
		o := orm.NewOrm()
		o.QueryTable(models.TableName("projects")).Filter("projectid", id).One(&project, "name")
		name = project.Name
		utils.SetCache("GetProjectName.id."+fmt.Sprintf("%d", id), name, cache_expire)
	}
	return name
}
func GetAllProjectName() []Projects {
	var err error
	var project []Projects

	err = utils.GetCache("GetProjectallName.", &project)
	if err != nil {
		cache_expire, _ := beego.AppConfig.Int("cache_expire")
		o := orm.NewOrm()
		o.QueryTable(models.TableName("projects")).All(&project)
		utils.SetCache("GetProjectallName.", project, cache_expire)
	}
	return project
}
func UpdateProject(id int64, updPro Projects) error {
	var pro Projects
	o := orm.NewOrm()
	pro = Projects{Id: id}

	pro.Name = updPro.Name
	pro.Aliasname = updPro.Aliasname
	pro.Started = updPro.Started
	pro.Ended = updPro.Ended
	pro.Desc = updPro.Desc
	pro.Projuserid = updPro.Projuserid
	pro.Produserid = updPro.Produserid
	pro.Testuserid = updPro.Testuserid
	pro.Publuserid = updPro.Publuserid
	//pro.Status = updPro.Status
	_, err := o.Update(&pro, "name", "aliasname", "started", "ended", "desc", "projuserid", "produserid", "testuserid", "publuserid")
	return err
}

func AddProject(updPro Projects) error {
	o := orm.NewOrm()
	pro := new(Projects)

	pro.Id = updPro.Id
	pro.Userid = updPro.Userid
	pro.Name = updPro.Name
	pro.Aliasname = updPro.Aliasname
	pro.Started = updPro.Started
	pro.Ended = updPro.Ended
	pro.Desc = updPro.Desc
	pro.Created = time.Now().Unix()
	pro.Status = 1
	_, err := o.Insert(pro)
	return err
}

func ChangeProjectStatus(id int64, status int) error {
	o := orm.NewOrm()

	pro := Projects{Id: id}
	err := o.Read(&pro, "projectid")
	if nil != err {
		return err
	} else {
		pro.Status = status
		_, err := o.Update(&pro)
		return err
	}
}

func ProjectPageExec(condArr map[string]interface{}, page int, offset int) (ops []ProjectsAll) {
	o := orm.NewOrm()
	var all []ProjectsAll
	o.Raw(projectPageSql(condArr, 1, page, offset)).QueryRows(&all)
	return all
}

func ProjectPageCountExec(condArr map[string]interface{}, page int, offset int) int64 {
	o := orm.NewOrm()
	var projectsAll int64
	o.Raw(projectPageSql(condArr, 0, page, offset)).QueryRow(&projectsAll)
	return projectsAll
}

/**
  组装sql
*/
func projectPageSql(condArr map[string]interface{}, ifsCount, page int, offset int) (string, []interface{}) {
	var sql string
	if ifsCount == 0 {
		sql = sql + `SELECT count(1) FROM (`
	}
	sql = sql + `
	SELECT
    pp.projectid id,
	  pp.*,
	  up.realname AS userrealname
	FROM  pms_projects pp
	  INNER JOIN pms_users_profile up ON up.userid=pp.userid
	WHERE 1 = 1 and exists(select 1 from pms_projects_team tm  
		WHERE pp.projectid =tm.projectid `
	param := make([]interface{}, 0, 0)
	if !utils.IsEmpty(condArr["userid"]) {
		sql = sql + ` and  tm.userid in(`
		sql1, value := cores.SqlInParam(condArr["userid"])
		sql = sql + sql1 + `)`
		param = append(param, value...)
	}
	sql = sql + `) `
	if !utils.IsEmpty(condArr["projectid"]) {
		sql = sql + ` and  pp.projectid=?`
		param = append(param, condArr["projectid"])
	}
	if !utils.IsEmpty(condArr["status"]) {
		sql = sql + ` and  pp.status in(`
		sql1, value := cores.SqlInParam(condArr["status"])
		sql = sql + sql1 + `)`
		param = append(param, value...)
	}
	if !utils.IsEmpty(condArr["keywords"]) {
		sql = sql + ` and  pp.name LIKE concat('%',?,'%')`
		param = append(param, condArr["keywords"])
	}

	if ifsCount == 0 {
		sql = sql + ` ) C`
	} else if ifsCount > 0 {
		if page < 1 {
			page = 1
		}
		offset = 200
		//if offset < 1 {
		//	offset, _ = beego.AppConfig.Int("pageoffset")
		//}
		start := (page - 1) * offset
		startStr := strconv.Itoa(start)
		offsetStr := strconv.Itoa(offset)
		sql = sql + ` order by created desc LIMIT ` + startStr + `,` + offsetStr
	}
	return sql, param
}
